import localforage from "localforage";
import {
  getSession,
  getStorage,
  setSession,
  setStorage,
  removeStorage,
  removeSession,
} from "@/utils/auth";
import storageJSON from "@/store/storage.json";
import { PiniaPluginContext } from "pinia";

const storage: any = storageJSON;

export type dbTypes = "session" | "local" | "indexedDB";

export interface PersistStrategy {
  key?: string;
  storage?: Storage;
  paths?: string[];
}
export interface PersistOptions {
  type?: dbTypes | "session";
}
declare module "pinia" {
  interface DefineStoreOptionsBase<S, Store> {
    persist?: PersistOptions | Boolean;
  }
}

/**
 * @function clearAlL
 * 清空所有缓存的store数据，如果传入type，则只清空该类型下的所有store数据，如果不传入，则清空所有支持的数据
 * @param {dbTypes} type 传入需要清空所有数据的类型
 * */
export const clearAlL = (type: dbTypes) => {
  for (const key in storage) {
    if (type) {
      removeStorageItem(key, type);
    } else {
      removeStorageItem(key, "indexedDB");
      removeStorageItem(key, "local");
      removeStorageItem(key, "session");
    }
  }
};

/**
 * @function removeItemFromPath 清空传入的path页面的对应store数据
 * @param {string} path 传入页面的path路径
 * */

export const removeItemFromPath = (path: string) => {
  if (storage) {
    for (const key in storage) {
      const el = storage[key];
      if (el?.length) {
        for (let i = 0; i < el.length; i++) {
          if (el[i] === path) {
            removeStorageItem(key, "indexedDB");
            removeStorageItem(key, "local");
            removeStorageItem(key, "session");
          }
        }
      }
    }
  }
};

/**
 * @function removeItem 移除传入的store名称对应的缓存数据
 * @param {string} name 传入store名称
 * @param {dbTypes} type 传入缓存类型,默认为session
 * */

export const removeStorageItem = (name: string, type: dbTypes) => {
  return new Promise((resolve, reject) => {
    if (!name) reject("name必须存在");
    if (!type) {
      removeSession(name);
      resolve(true);
      return;
    }
    let data;
    switch (type) {
      case "session":
        removeSession(name);
        resolve(true);
        break;
      case "local":
        removeStorage(name);
        resolve(true);
        break;
      case "indexedDB":
        localforage
          .dropInstance({
            name,
          })
          .then((res: unknown) => {
            resolve(JSON.parse(res as string));
          });
        break;
      default:
        resolve("");
        break;
    }
  });
};
/**
 * @function getStoreData 移除传入的store名称对应的缓存数据
 * @param {string} name 传入store名称
 * @param {dbTypes} type 传入缓存类型,默认为session
 * */
export const getStoreItem = (name: string, type: dbTypes) => {
  return new Promise((resolve, reject) => {
    if (!name) reject("name必须存在");
    if (!type) {
      resolve(JSON.parse(getSession(name)) || "");
      return;
    }
    let data;
    switch (type) {
      case "session":
        data = JSON.parse(getSession(name)) || "";
        resolve(data);
        break;
      case "local":
        data = JSON.parse(getStorage(name)) || "";
        resolve(data);
        break;
      case "indexedDB":
        localforage
          .createInstance({
            name,
          })
          .getItem(name)
          .then((res: unknown) => {
            resolve(JSON.parse(res as string));
          });
        break;
      default:
        resolve("");
        break;
    }
  });
};

/**
 * @function getStoreData 移除传入的store名称对应的缓存数据
 * @param {string} name 传入store名称
 * @param {dbTypes} type 传入缓存类型,默认为session
 * @param {string} data 传入缓存的数据，必须是字符串
 * */
export const setStoreData = (name: string, type: dbTypes, data: string) => {
  return new Promise((resolve, reject) => {
    if (!name) reject("name必须存在");
    if (!data) reject("data必须存在");
    if (!type) {
      setSession(name, data);
      resolve(true);
      return;
    }
    switch (type) {
      case "session":
        setSession(name, data);
        resolve(true);
        break;
      case "local":
        setStorage(name, data);
        resolve(true);
        break;
      case "indexedDB":
        localforage
          .createInstance({
            name,
          })
          .setItem(name, data);
        resolve(true);
        break;
      default:
        resolve("");
        break;
    }
  });
};

export const piniaStoragePlugin = async (
  context: PiniaPluginContext
): Promise<any> => {
  const { store, options }: any = context;
  if (options.persist) {
    if (store && store.$id) {
      let res = await getStoreItem(
        store.$id,
        (options!.persist!.type as dbTypes) || "session"
      );
      if (res) store.$state = res;
      store.$subscribe((_mutation: any, state: any) => {
        setStoreData(
          store.$id,
          (options!.persist!.type as dbTypes) || "session",
          JSON.stringify(state)
        );
      });
    }
  } else {
    console.log("89877");
  }
};
